/**
 * 
 */
package com.liusoft.android.fmagic;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 游戏数据和逻辑
 * @author Winter Lau
 */
public class MagicArray {

	private final static Random _rnd = new Random(System.currentTimeMillis());
	
	public final static byte DIR_DOWN 	= 0x01;	//向下移动
	public final static byte DIR_LEFT	= 0x02;	//向左移动
	public final static byte DIR_UP 	= 0x03;	//向上移动
	public final static byte DIR_RIGHT 	= 0x04;	//向右移动
	
	private byte[][] cells ;
	private int empty_cell_row;	//当前的空单元格行号
	private int empty_cell_col;	//当前的空单元格列号
	
	private int rowc;
	private int colc;
	
	public MagicArray(int rowc, int colc){
		//初始化数据
		this.rowc = rowc;
		this.colc = colc;
		this.empty_cell_row = rowc;
		this.empty_cell_col = colc;
		this.Reset(null);
	}
	
	/**
	 * 重置魔盘
	 */
	public void Reset(Byte[] p_cells) {
		if(p_cells == null){	
			int cells_row_size = rowc + 2;
			int cells_col_size = colc + 2;
			this.cells = new byte[cells_row_size][cells_col_size];
			for(int row=0;row<cells_row_size;row++){
				for(int col=0;col<cells_col_size;col++){
					if(row == 0 || col == 0 || row == (rowc+1) || col == (colc+1))
						this.cells[row][col] = -1;
					else{
						this.cells[row][col] = (byte)((row-1) * colc + col);
					}
				}
			}
			this.cells[rowc][colc] = 0;
			/*
			this.cells = new byte[][]{
					{-1,-1,-1,-1,-1,-1},
					{-1, 1, 2, 3, 4,-1},
					{-1, 5, 6, 7, 8,-1},
					{-1, 9,10,11,12,-1},
					{-1,13,14,15, 0,-1},
					{-1,-1,-1,-1,-1,-1}
			};*/
		}
		else
			this.SetCurrentCellData(p_cells);
	}

	/**
	 * 获取当前游戏状态
	 * @return
	 */
	public final byte[] GetCurrentCellData(){
		int idx = 0;
		byte[] data = new byte[(rowc+2) * (colc+2)];
		for(byte[] row : cells)
			for(byte cell : row)
				data[idx++] = cell;
		return data;
	}
	
	/**
	 * 设置游戏状态
	 * @param data
	 */
	private synchronized void SetCurrentCellData(Byte[] data){
		int c = colc + 2;
		for(int i = 0; i<data.length; i++) {
			int row = i / c;
			int col = i % c;
			cells[row][col] = data[i];
		}
	}
	
	/**
	 * 判断游戏是否结束
	 * @return
	 */
	public boolean Finish() {
		int CELL_COUNT = rowc * colc;
		for(int i=1;i<CELL_COUNT;i++){
			int col = i % colc;
			int row = i / colc + 1;
			if(col == 0){
				col = colc;
				row --;
			}
			if(cells[row][col] != i)
				return false;
		}
		return true;
	}

	/**
	 * 返回当前魔盘中的空单元格
	 * @return
	 */
	public int[] GetEmptyCell() {
		return new int[]{empty_cell_row,empty_cell_col};
	}
	
	/**
	 * 获取所有可移动的单元格
	 * @return
	 */
	public int[][] ListMovableCells() {
		int[] empty_cell = GetEmptyCell();
		List<int[]> movable_cells = new ArrayList<int[]>();
		if(cells[empty_cell[0]+1][empty_cell[1]]>0)
			movable_cells.add(new int[]{empty_cell[0]+1,empty_cell[1]});
		if(cells[empty_cell[0]][empty_cell[1]+1]>0)
			movable_cells.add(new int[]{empty_cell[0],empty_cell[1]+1});
		if(cells[empty_cell[0]-1][empty_cell[1]]>0)
			movable_cells.add(new int[]{empty_cell[0]-1,empty_cell[1]});
		if(cells[empty_cell[0]][empty_cell[1]-1]>0)
			movable_cells.add(new int[]{empty_cell[0],empty_cell[1]-1});
		int[][] i_movable_cells = new int[movable_cells.size()][2];
		movable_cells.toArray(i_movable_cells);
		return i_movable_cells;
	}
	
	/**
	 * 获取某个单元格的编号
	 * @param row
	 * @param col
	 * @return
	 */
	public byte GetCell(int row, int col) {
		try{
			return cells[row][col];
		}catch(ArrayIndexOutOfBoundsException e){
			return -1;
		}
	}
	
	/**
	 * 移动单元格
	 * @param row
	 * @param col
	 * @return
	 */
	public boolean Move(int row, int col) {
		byte[] dirs = new byte[]{DIR_UP,DIR_DOWN,DIR_LEFT,DIR_RIGHT};
		for(byte dir : dirs){
			if(Move(row,col,dir))
				return true;
		}
		return false;
	}
	
	public int[] GetMovableCell(int row, int col) {
		if(cells[row][col-1]==0)
			return new int[]{row,col-1};
		if(cells[row][col+1]==0)
			return new int[]{row,col+1};
		if(cells[row-1][col]==0)
			return new int[]{row-1,col};
		if(cells[row+1][col]==0)
			return new int[]{row+1,col};
		return null;
	}
	
	/**
	 * 打乱数组排列
	 */
	public void Confuse(int times) {
		for(int i=0;i<times;i++){
			int[][] movable_cells = ListMovableCells();
			int rnd_cell = _rnd.nextInt(movable_cells.length);
			Move(movable_cells[rnd_cell][0],movable_cells[rnd_cell][1]);
		}
	}
	
	/**
	 * 判断某个单元格是否可以移动
	 * @param row
	 * @param col
	 * @param direction
	 * @return
	 */
	protected boolean CanMove(int row, int col, byte direction) {
		switch(direction){
		case DIR_DOWN:
			row ++;
			break;
		case DIR_LEFT:
			col --;
			break;
		case DIR_UP:
			row --;
			break;
		case DIR_RIGHT:
			col ++;
			break;
		default:
			return false;
		}
		return cells[row][col]==0;
	}
	
	/**
	 * 单元格移位
	 * @param row
	 * @param col
	 * @param direction
	 * @return
	 */
	private boolean Move(int row, int col, byte direction) {
		int old_row = row;
		int old_col = col;
		switch(direction){
		case DIR_DOWN:
			row ++;
			break;
		case DIR_LEFT:
			col --;
			break;
		case DIR_UP:
			row --;
			break;
		case DIR_RIGHT:
			col ++;
			break;
		default:
			return false;
		}
		if(cells[row][col]==0){
			cells[row][col] = cells[old_row][old_col];
			cells[old_row][old_col] = 0;
			//保存当前空单元格的行列序号
			empty_cell_row = old_row;
			empty_cell_col = old_col;
			return true;
		}
		return false;	
	}
	
	/**
	 * 打印魔盘中所有单元格
	 * @param out
	 */
	private void PrintCells(PrintStream out) {
		for(int row=1;row<=rowc;row++){			
			for(int col=1;col<=colc;col++){
				out.print(cells[row][col]);
				out.print("\t");
			}
			out.println();
		}
	}
	
	public static void main(String[] args) {
		MagicArray md = new MagicArray(4,4);
		md.PrintCells(System.out);
		System.out.println(md.Finish());
		System.out.println("============================");
		md.Confuse(500);
		md.PrintCells(System.out);
		System.out.println(md.Finish());
	}
}
